<?php
namespace App\Http\Controllers\Api;

use App\Http\Requests\Api\GroupCourseOrderRequest;
use App\Http\Resources\Api\GroupCourseOrderResource;
use App\Models\GroupCourse;
use App\Models\GroupCourseOrder;
use App\Models\Tenant;
use Carbon\Carbon;
use EasyWeChat\Factory;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use function EasyWeChat\Kernel\Support\generate_sign;

class GroupCourseOrderController extends Controller
{
    public function index(Request $request)
    {
        $status = $request->status;
        $user = \Auth::getUser();
        $query = GroupCourseOrder::where([
            'tenant_id' => $user->tenant_id,
            'user_id' => $user->id,
            'is_paid' => true,
        ]);
        if ($status) {
            $query->where('status', $status);
        }
        $orders = $query
            ->orderByDesc('course_date')
            ->orderByDesc('paid_time')
            ->get();
        return api()->success(GroupCourseOrderResource::collection($orders));
    }

    public function store(GroupCourseOrderRequest $request)
    {
        $params = $request->only(['code', 'group_course_id', 'username', 'phone']);
        $user = \Auth::getUser();
        if (!$user) {
            return api()->failed('用户登录状态已过期，请返回首页重试');
        }
        $auth = $this->mini_program->auth->session($request->code);
        // 如果结果错误，说明 code 已过期或不正确
        if (isset($auth['errcode'])) {
            return api()->failed('code 不正确');
        }
        if (!$user->phone) {
            $user->phone = $params['phone'];
        }
        if (!$user->realname) {
            $user->realname = $params['username'];
        }
        $user->save();
        $group_course = GroupCourse::findOrFail($params['group_course_id']);
        // 可报名截止时间
        if ($group_course->schedule_type == GroupCourse::SCHEDULE_TYPE_WEEK) {
            $date = Carbon::now()->weekday($group_course->week - 1)->toDateString();
            $start_time = $date . ' ' . $group_course->course_start_time;
        } else {
            $date = $group_course->date;
            $start_time = $date . ' ' . $group_course->course_start_time;
        }
        if ($group_course->deadline) {
            $end_order_time = Carbon::parse($start_time)->subMinutes($group_course->deadline);
            if (Carbon::now()->gt($end_order_time)) {
                return api()->failed('已经过了报名截止时间，下次再来吧');
            }
        }

        // 只可预约当天的课程
        if (config("{$this->tenant->admin_prefix}.custom.group_course.only_apply_today")) {
            if (!Carbon::parse($start_time)->isToday()) {
                return api()->failed('只可预约当天的课程');
            }
        }

        // 检查当天报名此课程的人数有没有达到课程限定人数
        $group_course_order_count = $group_course->todayOrderCount();
        if ($group_course_order_count >= $group_course->people_number) {
            return api()->failed('此课程预约已满，看看其他课程吧');
        }
        // 检查用户当天有没有报名过此课程
        $user_order_count = $user->todayGroupCourseOrderCount();
        if ($user_order_count > 0) {
            return api()->failed('你今日已预约了此课程');
        }

        $env = app()->environment();

        // 开发环境支付一分钱
        if ($group_course->price > 0) {
            $total_fee = $env == 'local' ? 0.01 : $group_course->price;
            $is_paid = false;
        } else {
            $total_fee = 0;
            $is_paid = true;
        }

        \DB::beginTransaction();
        try {
            $order_sn = GroupCourseOrder::generateOrderNo();
            $body = "预约团课[{$group_course->title}]";
            $order_data = [
                'tenant_id' => $this->tenant->id,
                'user_id' => $user->id,
                'group_course_id' => $group_course->id,
                'order_sn' => $order_sn,
                'openid' => $auth['openid'],
                'body' => $body,
                'total_fee' => $total_fee,
                'is_paid' => $is_paid,
                'paid_time' => $is_paid ? Carbon::now()->toDateTimeString() : null,
                'course_date' => $date,
                'course_start_time' => $group_course->course_start_time,
                'course_end_time' => $group_course->course_end_time,
            ];

            $group_course_order = GroupCourseOrder::create($order_data);

            $weapp_path = "/pages/group_course_order/audit?id={$group_course_order->id}";
            $datetime = date("Ym/d", time());
            $audit_qrcode_path = "/images/{$this->tenant->admin_prefix}/group_course_order/{$group_course_order->id}/audit_qrcode/{$datetime}";
            $audit_qrcode_weapp_path = "/images/{$this->tenant->admin_prefix}/group_course_order/{$group_course_order->id}/audit_qrcode_weapp/{$datetime}";
            $filename = "{$group_course_order->order_sn}_group_course_order_qrcode". Str::random(10) .".png";
            $audit_qrcode = $audit_qrcode_path . '/' . $filename; // 小程序二维码
            $audit_qrcode_response = $this->mini_program->app_code->getQrCode($weapp_path, 230);
            if ($audit_qrcode_response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
                $rs = $audit_qrcode_response->saveAs(public_path() . $audit_qrcode_path, $filename);
                $audit_qrcode = $rs ? $audit_qrcode : '';
            } else {
                $audit_qrcode = '';
            }

            $audit_qrcode_weapp = $audit_qrcode_weapp_path . '/' . $filename; // 小程序码
            $audit_qrcode_weapp_response = $this->mini_program->app_code->getUnlimit('audit', ['page' => $weapp_path, 'width' => 600]);
            if ($audit_qrcode_weapp_response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
                $rs = $audit_qrcode_weapp_response->saveAs(public_path() . $audit_qrcode_weapp_path, $filename);
                $audit_qrcode_weapp = $rs ? $audit_qrcode_weapp : '';
            } else {
                $audit_qrcode_weapp = '';
            }

            $update = [
                'audit_qrcode' => $audit_qrcode,
                'audit_qrcode_weapp' => $audit_qrcode_weapp,
            ];
            $group_course_order->update($update);
            \DB::commit();
        } catch (\Exception $exception) {
            \DB::rollBack();
            return api()->failed("出错了:{$exception->getMessage()}");
        }

        if (!$is_paid) {
            $unify = [
                'body' => $body,
                'out_trade_no' => $order_sn,
                'total_fee' => round($total_fee * 100, 2),
                'trade_type' => 'JSAPI',
                'openid' => $auth['openid'],
                'notify_url' => config('app.url') . '/api/v1/group-course-orders/notify', // 单独设置回调地址
            ];
            $result = $this->mini_payment->order->unify($unify);
            if ($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS') {
                // 二次签名
                $params = [
                    'appId' => $this->mini_payment->getConfig()['app_id'],
                    'timeStamp' => time() . '',
                    'nonceStr' => $result['nonce_str'],
                    'package' => 'prepay_id=' . $result['prepay_id'],
                    'signType' => 'MD5',
                ];
                $params['paySign'] = generate_sign($params, $this->mini_payment->getConfig()['key']);
                $return['pay_params'] = $params;
                $return['order'] = $group_course_order;
                return api()->success($return);
            } else {
                return api()->failed('支付参数错误，请稍后再试');
            }
        }

        return api()->success($group_course_order);
    }

    public function show($id, Request $request)
    {
        $type = $request->get('type', '');
        $order = GroupCourseOrder::findOrFail($id);
        if ($type == 'pay_status') {
            return api()->success(['is_paid' => $order->is_paid]);
        }
        $order->mini_program = $this->mini_program;
        $resource = new GroupCourseOrderResource($order);
//        $resource->additional['mini_program'] = $this->mini_program;
        return api()->success($resource);
    }

    public function audit($id)
    {
        $order = GroupCourseOrder::findOrFail($id);
        if ($order->status == GroupCourseOrder::STATUS_USED) {
            return api()->failed('该课程已核销');
        }
        $user = \Auth::getUser();
        if (!$user) {
            return api()->failed('用户登录状态已过期，请返回首页重试');
        }
        if (!$user->coach) {
            return api()->failed('你还不是教练，无法核销课程');
        }
        $order->update([
            'status' => GroupCourseOrder::STATUS_USED,
            'audit_user_id' => $user->id,
            'audit_time' => Carbon::now()->toDateTimeString(),
        ]);

        return api()->success(new GroupCourseOrderResource($order));
    }

    public function cancel($id)
    {
        $order = GroupCourseOrder::findOrFail($id);
        if ($order->status == GroupCourseOrder::STATUS_USED) {
            return api()->failed('该课程已核销，不允许取消');
        }
        if ($order->status == GroupCourseOrder::STATUS_CANCELED) {
            return api()->failed('该课程已经是取消状态了');
        }
        $user = \Auth::getUser();
        if (!$user) {
            return api()->failed('用户登录状态已过期，请返回首页重试');
        }
        $order->update([
            'status' => GroupCourseOrder::STATUS_CANCELED,
            'cancel_reason' => '用户主动取消',
            'cancel_time' => Carbon::now()->toDateTimeString(),
        ]);

        return api()->success(new GroupCourseOrderResource($order));
    }

    public function notify()
    {
        $notify = $this->getNotify();
        $app_id = $notify['appid'];
        \Log::channel('pay_notify')->info('APPID:' . $app_id);
        $tenant = Tenant::where(['md5_weapp_id' => md5($app_id)])->first();
        $mini_payment_config = [
            'app_id' => $tenant->weapp_id,
            'mch_id' => $tenant->mch_id,
            'key' => $tenant->mch_key,
        ];
        $payment = Factory::payment($mini_payment_config);
        $response = $payment->handlePaidNotify(function ($message, $fail) use ($payment) {
            $order_sn = $message['out_trade_no'];
            $order = GroupCourseOrder::where(['order_sn' => $order_sn])->first();
            if ($order->is_paid && $order->paid_time) {
                return true;
            }
            $order_result = $payment->order->queryByOutTradeNumber($order_sn);
            if ($order_result['trade_state'] === 'SUCCESS' && $message['return_code'] === 'SUCCESS' &&
                array_get($message, 'result_code') === 'SUCCESS') {
                $order->is_paid = true;
                $order->paid_time = now();
                $order->transaction_id = $order_result['transaction_id'];
                $order->openid = $order_result['openid'];
//                $coach_order->total_fee = number_format($order_result['total_fee'] / 100, 2);
                $order->save();

                return true;
            } else {
                return $fail('通信失败，请稍后再通知我');
            }
        });
        return $response;
    }
}
